const rq = require('request-promise');
const X2JS = require('x2js');
const sequenceUtil = require('./sequenceUtil');
const moment = require('moment');
const payinfo = think.config('wxpay');

module.exports = {

  /**
   * 小程序下单
   */
  async miniproOrder({
    openid,
    outTradeNo,
    fee,
    ip,
    notifyUrl
  }) {
    const rt = await this.unifiedorder({
      openid,
      outTradeNo,
      fee,
      ip,
      notifyUrl
    });
    const data = {
      appId: payinfo.appId,
      timeStamp: moment().unix().toString(),
      nonceStr: sequenceUtil.randomLenStr(32),
      package: 'prepay_id=' + rt.prepay_id,
      signType: 'MD5'
    };
    data.paySign = this.sign(data);
    return data;
  },
  /**
   * 统一下单接口
   * @param {object} param0
   */
  async unifiedorder({
    openid,
    outTradeNo,
    fee,
    ip,
    notifyUrl
  }) {
    const url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    const nonceStr = sequenceUtil.randomLenStr(32);
    const data = {
      appid: payinfo.appId,
      mch_id: payinfo.mchId,
      nonce_str: nonceStr,
      openid,
      sign_type: 'MD5',
      out_trade_no: outTradeNo,
      total_fee: fee,
      spbill_create_ip: ip,
      notify_url: notifyUrl,
      trade_type: 'JSAPI',
      body: '支付费用'
    };
    data.sign = this.sign(data);
    const body = this.parse2Xml(data);
    think.logger.info('调用微信支付统一下单:', body);
    const result = await rq({
      url,
      method: 'POST',
      body: body
    });
    var x2js = new X2JS();
    const rt = x2js.xml2js(result).xml;
    think.logger.info('统一下单支付结果,JSON：', rt);
    if (rt.return_code === 'FAIL') {
      throw new Error(rt.return_msg);
    }
    if (rt.result_code === 'FAIL') {
      throw new Error(rt.err_code_des);
    }
    return rt;
  },
  parse2Xml(data) {
    return `<xml>
    <appid>${data.appid}</appid>
    <mch_id>${data.mch_id}</mch_id>
    <nonce_str>${data.nonce_str}</nonce_str>
    <sign>${data.sign}</sign>
    <sign_type>${data.sign_type}</sign_type>
    <out_trade_no>${data.out_trade_no}</out_trade_no>
    <total_fee>${data.total_fee}</total_fee>
    <spbill_create_ip>${data.spbill_create_ip}</spbill_create_ip>
    <notify_url>${data.notify_url}</notify_url>
    <trade_type>${data.trade_type}</trade_type>
    <openid>${data.openid}</openid>
    <body>${data.body}</body>
    </xml>`;
  },
  sign(data) {
    const params = [];
    Object.keys(data).sort().forEach(key => {
      params.push(`${key}=${data[key]}`);
    });
    params.push('key=' + payinfo.mchSecret);
    const paramsStr = params.join('&');
    think.logger.info('签名：', paramsStr);
    return think.md5(paramsStr).toUpperCase();
  }
};
